Add gdk_screen_get_monitor_workarea
authorMatthias Clasen <mclasen@redhat.com>
Sun, 18 Dec 2011 19:02:55 +0000 (14:02 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 18 Dec 2011 19:29:16 +0000 (14:29 -0500)
The function returns the part of a monitors area that should be
used for positioning popups, menus, etc. The only non-trivial
implementation atm is in the X backend, all the other backends
just return the full monitor area. The X implementation is
currently suboptimal, since it requires roundtrips to collect
the necessary information. It should be changed to monitor
the properties for changes, when XFixes allows to monitor
individual properties.
https://bugzilla.gnome.org/show_bug.cgi?id=641999

docs/reference/gdk/gdk3-sections.txt
gdk/broadway/gdkscreen-broadway.c
gdk/gdk.symbols
gdk/gdkscreen.c
gdk/gdkscreen.h
gdk/gdkscreenprivate.h
gdk/quartz/gdkscreen-quartz.c
gdk/wayland/gdkscreen-wayland.c
gdk/win32/gdkscreen-win32.c
gdk/x11/gdkscreen-x11.c

index 6204900377260c802c15405dd98349c250764d6a..ca4173bf7ae40df4c23244de84f7c189665bbb45 100644 (file)
@@ -199,6 +199,7 @@ gdk_screen_make_display_name
 gdk_screen_get_n_monitors
 gdk_screen_get_primary_monitor
 gdk_screen_get_monitor_geometry
+gdk_screen_get_monitor_workarea
 gdk_screen_get_monitor_at_point
 gdk_screen_get_monitor_at_window
 gdk_screen_get_monitor_height_mm
index 77b7a8863e14414096449e32b0a814839572dcbb..899ba9f729e066e7d0d61666e0a186b8afa1e174 100644 (file)
@@ -321,6 +321,7 @@ gdk_broadway_screen_class_init (GdkBroadwayScreenClass *klass)
   screen_class->get_monitor_height_mm = gdk_broadway_screen_get_monitor_height_mm;
   screen_class->get_monitor_plug_name = gdk_broadway_screen_get_monitor_plug_name;
   screen_class->get_monitor_geometry = gdk_broadway_screen_get_monitor_geometry;
+  screen_class->get_monitor_workarea = gdk_broadway_screen_get_monitor_geometry;
   screen_class->is_composited = gdk_broadway_screen_is_composited;
   screen_class->make_display_name = gdk_broadway_screen_make_display_name;
   screen_class->get_active_window = gdk_broadway_screen_get_active_window;
index 4222d69a28a38a2728fdf6466c7a96c51bdfd327..e6e366b401aa8e967046e883acc8920768ed3046 100644 (file)
@@ -271,6 +271,7 @@ gdk_screen_get_height_mm
 gdk_screen_get_monitor_at_point
 gdk_screen_get_monitor_at_window
 gdk_screen_get_monitor_geometry
+gdk_screen_get_monitor_workarea
 gdk_screen_get_monitor_height_mm
 gdk_screen_get_monitor_plug_name
 gdk_screen_get_monitor_width_mm
index c1de0f64e93674e416fea3a78e5f8e7c97ebec86..9493e168ff28f391a5ae5446f27371e16f6cf0ce 100644 (file)
@@ -750,12 +750,16 @@ gdk_screen_get_monitor_plug_name (GdkScreen *screen,
 /**
  * gdk_screen_get_monitor_geometry:
  * @screen: a #GdkScreen
- * @monitor_num: the monitor number, between 0 and gdk_screen_get_n_monitors (screen)
- * @dest: (out) (allow-none): a #GdkRectangle to be filled with the monitor geometry
+ * @monitor_num: the monitor number
+ * @dest: (out) (allow-none): a #GdkRectangle to be filled with
+ *     the monitor geometry
  *
  * Retrieves the #GdkRectangle representing the size and position of
  * the individual monitor within the entire screen area.
  *
+ * Monitor numbers start at 0. To obtain the number of monitors of
+ * @screen, use gdk_screen_get_n_monitors().
+ *
  * Note that the size of the entire screen area can be retrieved via
  * gdk_screen_get_width() and gdk_screen_get_height().
  *
@@ -769,6 +773,33 @@ gdk_screen_get_monitor_geometry (GdkScreen    *screen,
   GDK_SCREEN_GET_CLASS(screen)->get_monitor_geometry (screen, monitor_num, dest);
 }
 
+/**
+ * gdk_screen_get_monitor_workarea:
+ * @screen: a #GdkScreen
+ * @monitor_num: the monitor number
+ * @dest: (out) (allow-none): a #GdkRectangle to be filled with
+ *     the monitor workarea
+ *
+ * Retrieves the #GdkRectangle representing the size and position of
+ * the "work area" on a monitor within the entire screen area.
+ *
+ * The work area should be considered when positioning menus and
+ * similar popups, to avoid placing them below panels, docks or other
+ * desktop components.
+ *
+ * Monitor numbers start at 0. To obtain the number of monitors of
+ * @screen, use gdk_screen_get_n_monitors().
+ *
+ * Since: 3.4
+ */
+void
+gdk_screen_get_monitor_workarea (GdkScreen    *screen,
+                                 gint          monitor_num,
+                                 GdkRectangle *dest)
+{
+  GDK_SCREEN_GET_CLASS(screen)->get_monitor_workarea (screen, monitor_num, dest);
+}
+
 /**
  * gdk_screen_list_visuals:
  * @screen: the relevant #GdkScreen.
index 0f16a8f0f683723d70d3015aab99146ce53e06f2..a48c48bfe19c145c879a0db87f107965bad3ef64 100644 (file)
@@ -57,11 +57,15 @@ GList *      gdk_screen_list_visuals          (GdkScreen   *screen);
 GList *      gdk_screen_get_toplevel_windows  (GdkScreen   *screen);
 gchar *      gdk_screen_make_display_name     (GdkScreen   *screen);
 
-gint          gdk_screen_get_n_monitors        (GdkScreen *screen);
-gint          gdk_screen_get_primary_monitor   (GdkScreen *screen);
-void          gdk_screen_get_monitor_geometry  (GdkScreen *screen,
-                                                gint       monitor_num,
-                                                GdkRectangle *dest);
+gint         gdk_screen_get_n_monitors        (GdkScreen    *screen);
+gint         gdk_screen_get_primary_monitor   (GdkScreen    *screen);
+void         gdk_screen_get_monitor_geometry  (GdkScreen    *screen,
+                                               gint          monitor_num,
+                                               GdkRectangle *dest);
+void         gdk_screen_get_monitor_workarea  (GdkScreen    *screen,
+                                               gint          monitor_num,
+                                               GdkRectangle *area);
+
 gint          gdk_screen_get_monitor_at_point  (GdkScreen *screen,
                                                 gint       x,
                                                 gint       y);
index 42d03f259d1bcf2529cb608438c783baa2eae251..5ce9f07840c1935b13fef14fa30493a6b239d2c9 100644 (file)
@@ -62,6 +62,9 @@ struct _GdkScreenClass
   void         (* get_monitor_geometry)  (GdkScreen    *screen,
                                           gint          monitor_num,
                                           GdkRectangle *dest);
+  void         (* get_monitor_workarea)  (GdkScreen    *screen,
+                                          gint          monitor_num,
+                                          GdkRectangle *dest);
   GList *      (* list_visuals)          (GdkScreen *screen);
   GdkVisual *  (* get_system_visual)     (GdkScreen *screen);
   GdkVisual *  (* get_rgba_visual)       (GdkScreen *screen);
index 678a947243070ddf9355d94e863f3043613d02df..d104571ce65abe06851ace7bd9df17622959edd8 100644 (file)
@@ -462,6 +462,7 @@ gdk_quartz_screen_class_init (GdkQuartzScreenClass *klass)
   screen_class->get_monitor_height_mm = gdk_quartz_screen_get_monitor_height_mm;
   screen_class->get_monitor_plug_name = gdk_quartz_screen_get_monitor_plug_name;
   screen_class->get_monitor_geometry = gdk_quartz_screen_get_monitor_geometry;
+  screen_class->get_monitor_workarea = gdk_quartz_screen_get_monitor_geometry;
   screen_class->is_composited = gdk_quartz_screen_is_composited;
   screen_class->make_display_name = gdk_quartz_screen_make_display_name;
   screen_class->get_active_window = gdk_quartz_screen_get_active_window;
index cf7ef9034996d2abbe2742006cb719010bb344e7..310fc15a72a9da51a91bd3a2c1a50fd09fcf6514 100644 (file)
@@ -502,6 +502,7 @@ _gdk_screen_wayland_class_init (GdkScreenWaylandClass *klass)
   screen_class->get_monitor_height_mm = gdk_wayland_screen_get_monitor_height_mm;
   screen_class->get_monitor_plug_name = gdk_wayland_screen_get_monitor_plug_name;
   screen_class->get_monitor_geometry = gdk_wayland_screen_get_monitor_geometry;
+  screen_class->get_monitor_workarea = gdk_wayland_screen_get_monitor_geometry;
   screen_class->get_system_visual = gdk_wayland_screen_get_system_visual;
   screen_class->get_rgba_visual = gdk_wayland_screen_get_rgba_visual;
   screen_class->is_composited = gdk_wayland_screen_is_composited;
index d7a5815bf57d44ecfb9585184a07044eaa443be6..457858a2e75167c13e6044cb89a3de976e18526d 100644 (file)
@@ -222,6 +222,7 @@ gdk_win32_screen_class_init (GdkWin32ScreenClass *klass)
   screen_class->get_monitor_height_mm = gdk_win32_screen_get_monitor_height_mm;
   screen_class->get_monitor_plug_name = gdk_win32_screen_get_monitor_plug_name;
   screen_class->get_monitor_geometry = gdk_win32_screen_get_monitor_geometry;
+  screen_class->get_monitor_workarea = gdk_win32_screen_get_monitor_geometry;
   screen_class->get_system_visual = _gdk_win32_screen_get_system_visual;
   screen_class->get_rgba_visual = gdk_win32_screen_get_rgba_visual;
   screen_class->is_composited = gdk_win32_screen_is_composited;
@@ -238,4 +239,4 @@ gdk_win32_screen_class_init (GdkWin32ScreenClass *klass)
   screen_class->query_depths = _gdk_win32_screen_query_depths;
   screen_class->query_visual_types = _gdk_win32_screen_query_visual_types;
   screen_class->list_visuals = _gdk_win32_screen_list_visuals;
-}
\ No newline at end of file
+}
index fc3adaddd26a1a3e46c2c87f73676655b29b0f45..5574f639e071ebe9e848339a608d32fb81f094ef 100644 (file)
@@ -305,6 +305,113 @@ gdk_x11_screen_get_monitor_geometry (GdkScreen    *screen,
     *dest = x11_screen->monitors[monitor_num].geometry;
 }
 
+static int
+get_current_desktop (GdkScreen *screen)
+{
+  Display *display;
+  Window win;
+  Atom current_desktop, type;
+  int format;
+  unsigned long n_items, bytes_after;
+  unsigned char *data_return = NULL;
+  int workspace = 0;
+
+  display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
+  win = XRootWindow (display, GDK_SCREEN_XNUMBER (screen));
+
+  current_desktop = XInternAtom (display, "_NET_CURRENT_DESKTOP", True);
+
+  XGetWindowProperty (display,
+                      win,
+                      current_desktop,
+                      0, G_MAXLONG,
+                      False, XA_CARDINAL,
+                      &type, &format, &n_items, &bytes_after,
+                      &data_return);
+
+  if (type == XA_CARDINAL && format == 32 && n_items > 0)
+    workspace = (int) data_return[0];
+
+  if (data_return)
+    XFree (data_return);
+
+  return workspace;
+}
+
+static void
+get_work_area (GdkScreen    *screen,
+               GdkRectangle *area)
+{
+  Atom            workarea;
+  Atom            type;
+  Window          win;
+  int             format;
+  gulong          num;
+  gulong          leftovers;
+  gulong          max_len = 4 * 32;
+  guchar         *ret_workarea;
+  long           *workareas;
+  int             result;
+  int             disp_screen;
+  int             desktop;
+  Display        *display;
+
+  display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (screen));
+  disp_screen = GDK_SCREEN_XNUMBER (screen);
+  workarea = XInternAtom (display, "_NET_WORKAREA", True);
+
+  /* Defaults in case of error */
+  area->x = 0;
+  area->y = 0;
+  area->width = gdk_screen_get_width (screen);
+  area->height = gdk_screen_get_height (screen);
+
+  if (workarea == None)
+    return;
+
+  win = XRootWindow (display, disp_screen);
+  result = XGetWindowProperty (display,
+                               win,
+                               workarea,
+                               0,
+                               max_len,
+                               False,
+                               AnyPropertyType,
+                               &type,
+                               &format,
+                               &num,
+                               &leftovers,
+                               &ret_workarea);
+  if (result != Success ||
+      type == None ||
+      format == 0 ||
+      leftovers ||
+      num % 4 != 0)
+    return;
+
+  desktop = get_current_desktop (screen);
+
+  workareas = (long *) ret_workarea;
+  area->x = workareas[desktop * 4];
+  area->y = workareas[desktop * 4 + 1];
+  area->width = workareas[desktop * 4 + 2];
+  area->height = workareas[desktop * 4 + 3];
+
+  XFree (ret_workarea);
+}
+
+static void
+gdk_x11_screen_get_monitor_workarea (GdkScreen    *screen,
+                                     gint          monitor_num,
+                                     GdkRectangle *dest)
+{
+  GdkRectangle workarea;
+
+  gdk_x11_screen_get_monitor_geometry (screen, monitor_num, dest);
+  get_work_area (screen, &workarea);
+  gdk_rectangle_intersect (&workarea, dest, dest);
+}
+
 static GdkVisual *
 gdk_x11_screen_get_rgba_visual (GdkScreen *screen)
 {
@@ -1603,6 +1710,7 @@ gdk_x11_screen_class_init (GdkX11ScreenClass *klass)
   screen_class->get_monitor_height_mm = gdk_x11_screen_get_monitor_height_mm;
   screen_class->get_monitor_plug_name = gdk_x11_screen_get_monitor_plug_name;
   screen_class->get_monitor_geometry = gdk_x11_screen_get_monitor_geometry;
+  screen_class->get_monitor_workarea = gdk_x11_screen_get_monitor_workarea;
   screen_class->get_system_visual = _gdk_x11_screen_get_system_visual;
   screen_class->get_rgba_visual = gdk_x11_screen_get_rgba_visual;
   screen_class->is_composited = gdk_x11_screen_is_composited;